package com.audaque.springboot.foshanupload.doc.component;

import com.audaque.springboot.foshanupload.core.util.ResourceUtil;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.XMLWorkerFontProvider;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.xhtmlrenderer.layout.SharedContext;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;

import java.io.*;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.util.Map;

/**
 * @author zgb
 * @desc ...
 * @date 2022-05-18 17:02:21
 */
@Component
@Slf4j
public class ItextpdfProvider {

    public static final String FONT_CLASSPATH = "font/simhei.ttf";

    public void generator(Map<String, Object> data, String htmlTemplateClasspath, String cssTemplateClasspath, String dest) throws Exception {
        if (StringUtils.isBlank(htmlTemplateClasspath)) {
            throw new Exception("Itextpdf模板html资源路径不能为空");
        }
        String cssStr = "";
        if (StringUtils.isNotBlank(cssTemplateClasspath)) {
            //hutool
            //ResourceUtil中最核心的方法是getResourceObj，此方法可以根据传入路径是否为绝对路径而返回不同的实现。比如路径是：file:/opt/test，或者/opt/test都会被当作绝对路径，此时调用FileResource来读取数据。如果不满足以上条件，默认调用ClassPathResource读取classpath中的资源或者文件。
            String fileStr = cn.hutool.core.io.resource.ResourceUtil.getResource(cssTemplateClasspath).toURI().getPath();///E:/huaAo/code/myDiy/脚手架/单体/foshanupload/dbex/target/classes/html/template_freemarker.html
            cssStr = ResourceUtil.getURLSource(fileStr);
        }
        String htmlStr = freeMarkerRender(data, htmlTemplateClasspath);
        createPdf(htmlStr, cssStr, dest);
    }


    /**
     * freemarker渲染html
     */
    private String freeMarkerRender(Map<String, Object> data, String htmlTemplateClasspath) {
        Writer out = new StringWriter();
        try {

            Configuration freemarkerCfg = new Configuration();

            //hutool
            //ResourceUtil中最核心的方法是getResourceObj，此方法可以根据传入路径是否为绝对路径而返回不同的实现。比如路径是：file:/opt/test，或者/opt/test都会被当作绝对路径，此时调用FileResource来读取数据。如果不满足以上条件，默认调用ClassPathResource读取classpath中的资源或者文件。
            String fileStr = cn.hutool.core.io.resource.ResourceUtil.getResource(htmlTemplateClasspath).toURI().getPath();///E:/huaAo/code/myDiy/脚手架/单体/foshanupload/dbex/target/classes/html/template_freemarker.html


            //考虑到程序的可移植性，创建文件时建议大家选用"/",因为经过测试用java创建文件时在windows平台下用“/”也是可以的，java貌似在后台作过处理了。
            String separator = "/";
            int i = fileStr.lastIndexOf(separator);
            //前闭后开
            String dirStr = fileStr.substring(0, i);
            File dir = new File(dirStr);
            //设置模板目录
            freemarkerCfg.setDirectoryForTemplateLoading(dir);
            //获取模板名称，前闭后开
            String templateStr = fileStr.substring(i + 1, fileStr.length());
            // 获取模板,并设置编码方式
            Template template = freemarkerCfg.getTemplate(templateStr);
            template.setEncoding("UTF-8");
            // 合并数据模型与模板
            template.process(data, out); //将合并后的数据和模板写入到流中，这里使用的字符流
            out.flush();
            return out.toString();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                out.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return null;
    }

    private void createPdf(String htmlStr, String cssStr, String dest) throws Exception {
        if (htmlStr == null) {
            throw new Exception("找不到Itextpdf模板html");
        }
        if (StringUtils.isBlank(htmlStr)) {
            throw new Exception("Itextpdf模板html内容不能为空");
        }

        // step 1
        Document document = new Document();
        // step 2
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(dest));
        // step 3
        document.open();
        // step 4
        XMLWorkerFontProvider fontImp = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS);
        fontImp.register(FONT_CLASSPATH);

        XMLWorkerHelper.getInstance().parseXHtml(writer, document,
                new ByteArrayInputStream(htmlStr.getBytes()), new ByteArrayInputStream(cssStr.getBytes()), Charset.forName("UTF-8"), fontImp);
        // step 5
        document.close();

    }

    private void createPdfWithImg(String htmlStr, String dest, String imgClassPath) throws IOException, DocumentException, com.lowagie.text.DocumentException, URISyntaxException {
        ITextRenderer render = new ITextRenderer();
        ITextFontResolver fontResolver = render.getFontResolver();
        fontResolver.addFont(FONT_CLASSPATH, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        // 解析html生成pdf
        render.setDocumentFromString(htmlStr);
        //解决图片相对路径的问题
        //hutool
        //ResourceUtil中最核心的方法是getResourceObj，此方法可以根据传入路径是否为绝对路径而返回不同的实现。比如路径是：file:/opt/test，或者/opt/test都会被当作绝对路径，此时调用FileResource来读取数据。如果不满足以上条件，默认调用ClassPathResource读取classpath中的资源或者文件。
        String classPath = cn.hutool.core.io.resource.ResourceUtil.getResource(imgClassPath).toURI().getPath();
        /**
         file协议只能在本地访问，file无法实现跨域
         如:获取C盘某个文件
         file:///C:/Users/CLi/AppData/Local/Temp/WindowsLiveWriter1627300719/supfiles52F410/wangdan-se-436963[2].jpg
         等价于
         C:/Users/CLi/AppData/Local/Temp/WindowsLiveWriter1627300719/supfiles52F410/wangdan-se-436963[2].jpg*/
        String logoFilePath = "file://" + classPath;

        SharedContext sharedContext = render.getSharedContext();
        sharedContext.setBaseURL(logoFilePath);
        render.layout();
        render.createPDF(new FileOutputStream(dest));
    }


}
